package com.linln.common.jpahelper;

import org.springframework.data.jpa.domain.Specification;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

/**
 * 定义一个查询条件容器
 *
 * @param <T>
 */
public class Criteria<T> implements Specification<T> {
    private List<Criterion> criterions = new ArrayList<>();

    private List<List<Criterion>> orCris=new ArrayList<>();



    public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
                                 CriteriaBuilder builder) {
        List<Predicate> predicatesAnd = new ArrayList<>();
        List<List<Predicate>> predicatesOrGroups=new ArrayList<>();


        List<Predicate> wheres=new ArrayList<>();

        if (!criterions.isEmpty()) {
            for(Criterion c : criterions){
                if(c!=null){
                    predicatesAnd.add(c.toPredicate(root, query,builder));
                }
            }
        }
        if(!orCris.isEmpty()){
            for(List<Criterion> groupCtr :orCris){
                List<Predicate> predicatesOrGroup=new ArrayList<>();
                for(Criterion c :groupCtr){
                    if(c!=null){
                        predicatesOrGroup.add(c.toPredicate(root, query,builder));
                    }
                }
                predicatesOrGroups.add(predicatesOrGroup);
            }
        }

        if(!predicatesAnd.isEmpty()){
            Predicate[] addPre = new Predicate[predicatesAnd.size()];
            Predicate predicatesWhere = builder.and(predicatesAnd.toArray(addPre));
            wheres.add(predicatesWhere);
        }

        if(!predicatesOrGroups.isEmpty()){
            for(List<Predicate> orPres:predicatesOrGroups){
                Predicate[] orPre = new Predicate[orPres.size()];
                Predicate predicatesOr = builder.or(orPres.toArray(orPre));
                wheres.add(predicatesOr);
//                query.where(predicatesOr);
            }
        }

        if(!wheres.isEmpty()){
            Predicate[] wherePre = new Predicate[wheres.size()];
            query.where( wheres.toArray(wherePre));
        }

        return query.getRestriction();
    }
    /**
     * 增加简单条件表达式
     * @Methods Name add
     * @param
     */
    public Criteria addAnd(Criterion criterion){
        if(criterion!=null){
            criterions.add(criterion);
        }
        return this;
    }

    public Criteria addOrGroup(List<Criterion> ors){
        if(ors!=null){
            orCris.add(ors);
        }
        return  this;
    }


}